#include "src/scene/texture.h"

#include "src/scene/object.h"

#include <GL/glu.h>
#include <iostream>

#if USE_CONSOLE
Texture::Texture(const QString &_imagePathName, unsigned int _repeatTimesU, unsigned int _repeatTimesV, unsigned int _coloringType, unsigned int _mappingType)
    : textureImagePathName(_imagePathName), mappingType(_mappingType), coloringType(_coloringType), repeatTimesU(_repeatTimesU), repeatTimesV(_repeatTimesV)
{
    textureImage.load(_imagePathName);
}
#else //USE_CONSOLE

#include "src/interface/glwidget.h"

Texture::Texture(GLWidget *_glWidget, const QString &_imagePathName, unsigned int _repeatTimesU, unsigned int _repeatTimesV, unsigned int _coloringType, unsigned int _mappingType)
    : textureImagePathName(_imagePathName), mappingType(_mappingType), coloringType(_coloringType), repeatTimesU(_repeatTimesU), repeatTimesV(_repeatTimesV)
{
//    std::cout <<"Image format " << _image.format() << std::endl;
//    std::cout <<"textureImage format " << textureImage.format() << std::endl;

    if(_glWidget)
    {
        textureImage.load(_imagePathName);
        glTexture = _glWidget->bindTexture(textureImage);
    }
//    _image.convertToFormat(QImage::Format_RGB32)
}

void Texture::useTexture()
{
    glBindTexture(GL_TEXTURE_2D, glTexture);

    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_REPEAT);

    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_BASE_LEVEL, 0);
    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_LEVEL, 0);


    GLfloat env_color[4] = {1, 0, 0, 1}, border_color[4] = {1, 1, 0, 1};

    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
    glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, env_color);
    glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, border_color);

//    gluBuild2DMipmaps(GL_TEXTURE_2D, 3, 100, 100, GL_RGB, GL_UNSIGNED_BYTE, &glTexture);
//    gluBuild2DMipmaps(GL_TEXTURE_2D, 3, iwidth, iheight, GL_RGB, GL_UNSIGNED_BYTE, image);
}
#endif //USE_CONSOLE

Texture::~Texture()
{
    glDeleteTextures(1, &glTexture);
}

void Texture::getMinMax(double *_minU, double *_maxU, double *_minV, double *_maxV) const
{
    *_minU = 0; //testar com 0, ao invez de dar a metade
    *_maxU = repeatTimesU;
    *_minV = 0; //testar com 0, ao invez de dar a metade
    *_maxV = repeatTimesV;
}

Color Texture::getColor(Object *_obj, const Vector3D &_point) const
{
//    #if DEBUG
//    std::cout << "\n\n------------------------------------------------\n\nProcurando a textura" << std::endl;
//    #endif //DEBUG

    double u, v;
    _obj->getTextureUV(&u, &v, _point, mappingType);

//    #if DEBUG
//    std::cout << "U " << u << "\nV " << v << std::endl;
//    #endif //DEBUG
//
//    int x = ((int)(u*textureImage.width()) % repeatTimesU)/ repeatTimesU;
//    int y = ((int)(v*textureImage.height()) % repeatTimesV)/ repeatTimesV;

    int w = textureImage.width();
    int h = textureImage.height();

    int x = (int)(u * w * repeatTimesU) % w;
    int y = (int)(v * h * repeatTimesV) % h;
//    #if DEBUG
//    std::cout << "X " << x //<< "(" << u << " * " << textureImage.width() << " * "<< repeatTimesU << ")"
//            << "\nY " << y //<< "(" << v << " * " << textureImage.height() << " * "<< repeatTimesV << ")"
//            << std::endl;
//    #endif //DEBUG

    QRgb color = textureImage.pixel(x, y);

    Color result(qRed(color), qGreen(color), qBlue(color));
//    #if DEBUG
//    result.print();
//    #endif //DEBUG
    return result/255.0;
}
